#include "../inc/segmentlist.h"

SegmentList::SegmentList()
{
	segments.clear();
}

SegmentList::SegmentList(const SegmentList &_sl)
{
	segments = _sl.segments;
}

SegmentList::~SegmentList()
{
	segments.clear();
}

SegmentList& SegmentList::operator = ( const SegmentList& _sl )
{
	segments.clear();
	segments = _sl.segments;

	return *this;
}

list<Segment*> SegmentList::getSegments()
{
	return segments;
}

list<Segment*>::iterator SegmentList::getBegin()
{
    return segments.begin();
}

list<Segment*>::iterator SegmentList::getEnd()
{
    return segments.end();
}

void SegmentList::setSegments( list<Segment *> _sl)
{
	segments.clear();
	segments = _sl;
}

void SegmentList::clear()
{
	segments.clear();
}

void SegmentList::createFromMap_Eq (double _thresh, Mesh _mesh, Map _map)
{
	int*	mark = (int*) malloc ( _mesh.getNVerts() * sizeof(int) );
	
	for ( int i = 0 ; i < _mesh.getNVerts() ; i++ )
		mark[i] = -1;
	
	/* For each vertices of the mesh, we look if it can be a seed for a segment. 
	   The mark array is an array that permit not computing several times the same segment from different seeds.
	   It has been initialized to -1.
	*/
	for ( int i = 0 ; i < _mesh.getNVerts() ; i++ )
	{
		/* If the vertex value verifies the criteria. */
		if ( _map.getIData( _mesh.getIVert(i)->getID() ) == _thresh )
		{
			/* If the vertex has not been marked yet
			   we have to considerate the vertex as a seed and add the created segment to the list.
			*/
			if ( mark [ _mesh.getIVert( i )->getID() ] == -1 )
			{
				Segment* toAdd = new Segment();
				toAdd->createFromSeed_Eq( _mesh.getIVert(i), _mesh, _map, mark );
				segments.push_back( toAdd );
			}
		}
	}
	
	/* Don't forget to free the memory allocated. */
	free ( mark );	
}

void SegmentList::createFromMap_LeEq (double _thresh, Mesh _mesh, Map _map)
{
	int*	mark = (int*) malloc ( _mesh.getNVerts() * sizeof(int) );
	
	for ( int i = 0 ; i < _mesh.getNVerts() ; i++ )
		mark[i] = -1;
	
	/* For each vertices of the mesh, we look if it can be a seed for a segment. 
	   The mark array is an array that permit not computing several times the same segment from different seeds.
	   It has been initialized to -1.
	*/
	for ( int i = 0 ; i < _mesh.getNVerts() ; i++ )
	{
		/* If the vertex value verifies the criteria. */
		if ( _map.getIData( i ) <= _thresh )
		{
			/* If the vertex has not been marked yet OR (it has been marked by a higher depth segment) ,
			   we have to considerate the vertex as a seed and add the created segment to the list.
			*/
			if ( mark [ i ] == -1 || mark [ i ] > _map.getIData( i ) )
			{
				Segment* toAdd = new Segment();
				toAdd->createFromSeed_LeEq( _mesh.getIVert(i), _mesh, _map, mark );
				segments.push_back( toAdd );
			}
		}
	}
	
	/* Don't forget to free the memory allocated. */
	free ( mark );	
}

void SegmentList::createFromMap_GrEq (double _thresh, Mesh _mesh, Map _map)
{
	int*	mark = (int*) malloc ( _mesh.getNVerts() * sizeof(int) );
	
	for ( int i = 0 ; i < _mesh.getNVerts() ; i++ )
		mark[i] = -1;
	
	/* For each vertices of the mesh, we look if it can be a seed for a segment. 
	   The mark array is an array that permit not computing several times the same segment from different seeds.
	   It has been initialized to -1.
	*/
	for ( int i = 0 ; i < _mesh.getNVerts() ; i++ )
	{
		/* If the vertex value verifies the criteria. */
		if ( _map.getIData( _mesh.getIVert(i)->getID() ) >= _thresh )
		{
			/* If the vertex has not been marked yet OR (it has been marked by a lesser depth segment) ,
			   we have to considerate the vertex as a seed and add the created segment to the list.
			*/
			if ( mark [ _mesh.getIVert( i )->getID() ] == -1 || mark [ _mesh.getIVert( i )->getID() ] < _map.getIData( _mesh.getIVert(i)->getID() ) )
			{
				Segment* toAdd = new Segment();
				toAdd->createFromSeed_GrEq( _mesh.getIVert(i), _mesh, _map, mark );
				segments.push_back( toAdd );
			}
		}
	}
	
	/* Don't forget to free the memory allocated. */
	free ( mark );	
}

void SegmentList::addSegment(Segment *_s)
{
	segments.push_back( _s );
}

void SegmentList::removeSegment(Segment *_s)
{
	for ( list<Segment*>::iterator it = getBegin() ; it != getEnd() ; it++ )
	{
		if ( *it == _s )
		{
			segments.erase( it );
			return;
		}
	}
}

Segment* SegmentList::extractMinimumDepth()
{
	double min = INT_MAX;
	Segment* rslt;
	list<Segment*>::iterator itMin;
	
	for ( list<Segment*>::iterator it = getBegin() ; it != getEnd() ; it++ )
	{
		if ( (*it)->getDepth() < min )
		{
			min = (*it)->getDepth();
			itMin = it;
		}
	}
	
	rslt = (*itMin);
	
	segments.erase(itMin);

	return rslt;
}

Segment* SegmentList::extractMaximumDepth()
{
	double max = INT_MIN;
	Segment* rslt = NULL;
	list<Segment*>::iterator itMax;
	
	for ( list<Segment*>::iterator it = segments.begin() ; it != segments.end() ; it++ )
	{
		if ( (*it)->getDepth() > max )
		{
			max = (*it)->getDepth();
			itMax = it;
		}
	}

	rslt = (*itMax);
	
	segments.erase( itMax );
	
	return rslt;
}

bool SegmentList::contains(Segment *_s)
{
	for ( list<Segment*>::iterator it = segments.begin() ; it != segments.end() ; it++ )
	{
		if ( *it == _s )
			return true;
	}
	
	return false;
}

void SegmentList::printIDS()
{
	int cpt = 0;
	
	if ( segments.empty() )
	{
		cout<<"Liste vide"<<endl;
		return;
	}
	
	cout<<"X";
	for ( list<Segment*>::iterator it = segments.begin() ; it != segments.end() ; it++ )
	{
		cout<<"[ N:"<<cpt<<" ID: "<<(*it)->getID()<<" ]=>";
		cpt++;
	}
	cout<<"X"<<endl;
}

void SegmentList::display()
{
	for ( list<Segment*>::iterator it = segments.begin() ; it != segments.end() ; it++ )
	{
		(*it)->display();
	}
}

void SegmentList::display( int _i )
{
	if ( _i > segments.size() )
	{
		cout<<"On a depasse la taille de la liste la"<<endl;
		return;
	}
	
	int i = 0;
	for ( list<Segment*>::iterator it = segments.begin() ; it != segments.end() ; it++ )
	{
		if ( i == _i )
			(*it)->display();
		i++;
	}
}
